home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / piano.zip / PIANO.BAK < prev    next >
Text File  |  1992-09-06  |  13KB  |  401 lines

  1. // filename    PIANO.CPP
  2. // author    Robert Upleger
  3. // intent    To simulate a piano keyboard.
  4. //        To use graphics to display a piano keyboard on the screen.
  5. //        To play the proper sound for each corresponding key
  6. //        either from the computer keyboard or from disk.
  7. //        To "light-up" each note that is played.
  8. //
  9. // project    To demonstrate the various features of Turbo C++
  10. //              as described in Lafore.   This program includes the use
  11. //        of inheritence, external files, and virtual functions.
  12. //
  13. // class    CSc 311-31  Ahlborn
  14. // assignment    Programming assignment #4 - Final Project
  15. // due-date    07-31-92
  16. // reference    Robert LaFore (The Waite Group's)
  17. //        "Object-Oriented Programming in Turbo C++"
  18. //        Waite Group Press, 1992 - Chapter 11 & 15
  19. //
  20. // description  The program starts with a display of a piano keyboard.
  21. //        A menu of options appears below the piano.
  22. //        The user is presented with four options:
  23. //
  24. //        OPTION #1
  25. //        This option will display the keys on the computer
  26. //        keyboard necessary to play the piano.
  27. //
  28. //        OPTION #2
  29. //        This option will play an old Motown song:
  30. //        'You really got a hold on me.'
  31. //
  32. //        OPTION #3
  33. //        This option plays the scales, forward then backward.
  34. //
  35. //        OPTION #4
  36. //        This option terminates the program.
  37. //
  38.  
  39. #include <graphics.h>        // for initgraph(), etc
  40. #include <stdlib.h>        // for exit()
  41. #include <conio.h>        // for getch()
  42. #include <dos.h>        // for delay(), sound(), etc
  43. #include <fstream.h>        // for cout, etc
  44. #include <ctype.h>        // for toupper()
  45.  
  46. enum keystatus { notpushed, pushed } ;        // keyboard status
  47. keystatus kstatus = notpushed ;            // initialize to notpushed
  48.  
  49. struct Note        // structure for note data stored on disk
  50.     {
  51.     char letter ;    // a letter from the keyboard
  52.     float delay ;    // the sound delay in milliseconds
  53.     };
  54.  
  55. class key        // base class for a key type
  56.     {
  57.     protected:
  58.         int left, top, right, bottom ;    // drwaing coordinates
  59.         int color ;            // key color
  60.         float freq;            // note frequency
  61.     public:
  62.         key( int l, int t, int r,  int b , float f )
  63.             { left=l; top=t; right=r; bottom=b; freq=f; }
  64.         virtual void drawkey() = 0 ;     // pure virtual function
  65.         virtual void makesound ( float del ) = 0 ;
  66.     };
  67.  
  68.  
  69. class Lkey : public key        // piano key with a left nub
  70.     {
  71.     public:
  72.         Lkey( int l, int t, int r, int b, float f ) :
  73.             key( l, t, r,  b, f )  {}
  74.         void drawkey()
  75.             {
  76.             // draw key and fill it with pattern & color
  77.             int intarr[ 12 ] ;
  78.             int* p = intarr ;
  79.             *(p +0)  = left +  8      ;    *(p +1)  = top ;
  80.             *(p +2)  = right      ;    *(p +3)  = top ;
  81.             *(p +4)  = right      ;    *(p +5)  = bottom ;
  82.             *(p +6)  = left     ;    *(p +7)  = bottom ;
  83.             *(p +8)  = left     ;    *(p +9)  = top+64 ;
  84.             *(p+10)  = left + 8     ;    *(p+11)  = top+64 ;
  85.             color = ( ( kstatus ) ? BLUE : WHITE ) ;
  86.             setfillstyle( SOLID_FILL , color ) ;
  87.             fillpoly( 6 , p ) ;
  88.             setcolor( 0 );
  89.             rectangle( left+1, top+1, right-1, bottom-1 );
  90.             }
  91.         void makesound ( float del )
  92.             {
  93.             sound( freq ) ;        // play note
  94.             delay( del ) ;        // delay millliseconds
  95.             nosound() ;        // stop sound
  96.             }
  97.  
  98.     };
  99.  
  100. class Rkey : public key         // piano key with a right nub
  101.     {
  102.     public:
  103.         Rkey( int l, int t, int r, int b, float f ) :
  104.             key( l, t, r,  b, f )  {}
  105.         void drawkey()
  106.             {
  107.             // draw key and fill it with pattern & color
  108.             int intarr[ 12 ] ;
  109.             int* p = intarr ;
  110.             *(p +0)  = left           ;    *(p +1)  = top ;
  111.             *(p +2)  = left +  16  ;    *(p +3)  = top ;
  112.             *(p +4)  = left +  16  ;    *(p +5)  = top+64 ;
  113.             *(p +6)  = right       ;    *(p +7)  = top+64 ;
  114.             *(p +8)  = right       ;    *(p +9)  = bottom ;
  115.             *(p+10)  = left        ;    *(p+11)  = bottom ;
  116.             color = ( ( kstatus ) ? BLUE : WHITE ) ;
  117.             setfillstyle( SOLID_FILL , color ) ;
  118.             fillpoly( 6 , p ) ;
  119.             setcolor( 0 ) ;
  120.             rectangle( left+1, top+1, right-1, bottom-1 );
  121.             }
  122.         void makesound ( float del )
  123.             {
  124.             sound( freq ) ;        // play note
  125.             delay( del ) ;        // delay millliseconds
  126.             nosound() ;        // stop sound
  127.             }
  128.     };
  129.  
  130.  
  131. class Bkey : public key        // the black piano keys
  132.     {
  133.     public:
  134.         Bkey( int l, int t, int r, int b, float f ) :
  135.             key( l, t, r,  b, f )  {}
  136.         void drawkey()
  137.             {
  138.             // draw key and fill it with pattern & color
  139.             int intarr[ 10 ] ;
  140.             int* p = intarr ;
  141.             *(p +0)  =  left     ;    *(p +1)  = top ;
  142.             *(p +2)  =  right     ;    *(p +3)  = top ;
  143.             *(p +4)  =  right     ;    *(p +5)  = bottom ;
  144.             *(p +6)  =  left     ;    *(p +7)  = bottom ;
  145.             *(p +8)  =  left     ;    *(p +9)  = top ;
  146.             color = ( ( kstatus ) ? RED : BLACK ) ;
  147.             setfillstyle( SOLID_FILL, color ) ;
  148.             fillpoly( 5, p ) ;
  149.             setcolor( getmaxcolor() ) ;
  150.             rectangle( left+1, top+1, right-1, bottom-1 ) ;
  151.             }
  152.         void makesound ( float del )
  153.             {
  154.             sound( freq ) ;        // play note
  155.             delay( del ) ;        // delay millliseconds
  156.             nosound() ;        // stop sound
  157.             }
  158.     } ;
  159.  
  160. class Ckey : public key        // piano keys inbetween the black keys
  161.     {
  162.     public:
  163.         Ckey( int l, int t, int r, int b, float f ) :
  164.             key( l, t, r,  b, f )  {}
  165.         void drawkey()
  166.             {
  167.             // draw key and fill it with pattern & color
  168.             int intarr[ 16 ] ;
  169.             int* p = intarr ;
  170.             *(p +0)  = left +   8     ;    *(p +1)  = top ;
  171.             *(p +2)  = left +  16     ;    *(p +3)  = top ;
  172.             *(p +4)  = left +  16     ;    *(p +5)  = top+64 ;
  173.             *(p +6)  = right     ;    *(p +7)  = top+64 ;
  174.             *(p +8)  = right     ;    *(p +9)  = bottom ;
  175.             *(p+10)  = left           ;    *(p+11)  = bottom ;
  176.             *(p+12)  = left       ;       *(p+13)  = top+64 ;
  177.             *(p+14)  = left +   8    ;       *(p+15)  = top+64 ;
  178.             color = ( ( kstatus ) ? BLUE : WHITE ) ;
  179.             setfillstyle( SOLID_FILL , color ) ;
  180.             fillpoly( 8 , p ) ;
  181.             setcolor( 0 ) ;
  182.             rectangle( left+1, top+1, right-1, bottom-1 );
  183.             }
  184.         void makesound ( float del )
  185.             {
  186.             sound( freq ) ;        // play note
  187.             delay( del ) ;        // delay millliseconds
  188.             nosound() ;        // stop sound
  189.             }
  190.     };
  191.  
  192.  
  193.  
  194. int main()
  195.     {
  196.     int gdriver = DETECT ;             // auto detection
  197.     int gmode, errorcode ;            
  198.     initgraph( &gdriver, &gmode, "" );    // initialize graphics
  199.     errorcode = graphresult();              // get error code
  200.     if ( errorcode != 0 )            // an error occurred
  201.         {
  202.         cout << "Graphics error: " << grapherrormsg( errorcode ) ;
  203.         getch() ;
  204.         exit(1) ;    // exit program
  205.         }
  206.  
  207.  
  208.     // initialize piano keys           note          keyboard
  209.     // --------------------------------      ---------   --------
  210.  
  211.     Rkey A(  40, 40,  64, 160, 261.63 ) ;    // c natural     char a
  212.     Bkey W(  56, 40,  72, 104, 277.48 ) ;    // c sharp      char w
  213.     Ckey S(  64, 40,  88, 160, 293.66 ) ;    // d natural    char s
  214.     Bkey E(  80, 40,  96, 104, 311.65 ) ;    // e flat    char e
  215.     Lkey D(  88, 40, 112, 160, 329.63 ) ;    // e natural    char d
  216.     Rkey F( 112, 40, 136, 160, 349.23 ) ;    // f natural    char f
  217.     Bkey T( 128, 40, 144, 104, 370.62 ) ;      // f sharp    char t
  218.     Ckey G( 136, 40, 160, 160, 392.00 ) ;    // g natural    char g
  219.     Bkey Y( 152, 40, 168, 104, 416.00 ) ;    // g sharp    char y
  220.     Ckey H( 160, 40, 184, 160, 440.00 ) ;    // a natural    char h
  221.     Bkey U( 176, 40, 192, 104, 466.94 ) ;    // a sharp    char u
  222.     Lkey J( 184, 40, 208, 160, 493.88 ) ;    // b natural     char j
  223.     Rkey K( 208, 40, 232, 160, 523.25 ) ;    // c natural    char k
  224.     Bkey O( 224, 40, 240, 104, 555.28 ) ;    // c sharp    char o
  225.     Ckey L( 232, 40, 256, 160, 587.32 ) ;    // d natural    char l
  226.  
  227.     // set-up pointers to all the keys
  228.  
  229.     Lkey* Lptr ;     // pointer to a left key
  230.     Bkey* Bptr ;    // pointer to a black key
  231.     Rkey* Rptr ;    // pointer to a right key
  232.     Ckey* Cptr ;    // pointer to a center key
  233.  
  234.     // initialize pointers to corresponding note addresses
  235.     // and put pointers into array 'keyptr'
  236.  
  237.     key* keyptr[ 15 ] = {     Rptr = &A , Bptr = &W , Cptr = &S ,
  238.                 Bptr = &E , Lptr = &D , Rptr = &F ,
  239.                 Bptr = &T , Cptr = &G , Bptr = &Y ,
  240.                 Cptr = &H , Bptr = &U , Lptr = &J ,
  241.                 Rptr = &K , Bptr = &O , Cptr = &L } ;
  242.  
  243.     // draw piano keyboard with virtual function 'drawkey()'
  244.  
  245.     for ( int j=0 ; j<15 ; j++ )
  246.         keyptr[ j ] -> drawkey() ;
  247.  
  248.     // initialize variables and function prototypes
  249.  
  250.     Note note ;            // note structure variable
  251.     fstream file ;            // file from a disk
  252.     char ch  ;            // input character
  253.     int mainmenu() ;             // prototype
  254.     int noteptr( char ) ;        // prototype
  255.     void cleartext() ;        // prototype
  256.     void showkeyboard() ;        // prototype
  257.     void invalidoption() ;        // prototype
  258.     char option ;            // input option
  259.     option = toupper(mainmenu());    // initialize option from menu
  260.  
  261.     
  262.  
  263.     do // the option that the user entered
  264.         {
  265.         cleartext() ;        // clear the option menu
  266.         switch( option )    // decide what option to do
  267.             {
  268.             case 'A': {    // do the piano keyboard
  269.                   showkeyboard() ;  // show keyboard menu
  270.                   do    // keep getting a note
  271.                     {
  272.                     ch = getch() ;
  273.                     // assign the key an array index
  274.                     int i = noteptr( ch ) ;
  275.                     // if valid play the piano note
  276.                     if ( i != 99 )
  277.                         {
  278.                         // change keypushed status
  279.                         kstatus = pushed ;
  280.                         // draw pushed key
  281.                         keyptr[ i ] -> drawkey() ;
  282.                         // play the sound
  283.                         keyptr[ i ] -> makesound(200);
  284.                         // change keypushed ststus
  285.                         kstatus = notpushed ;
  286.                         // draw unpushed key
  287.                         keyptr[ i ] -> drawkey() ;
  288.                         }
  289.                     }
  290.                 while ( ch != 'x' );
  291.                 break;
  292.                 }
  293.             case 'B':    // play one of two songs
  294.             case 'C': {
  295.                   if ( option == 'B' )
  296.                     // play Motown
  297.                     file.open( "SONG.DAT" , ios::in ) ;
  298.                     // else play the scales
  299.                   else     file.open( "SONG1.DAT" , ios::in );
  300.                   file.seekg(0) ; // goto begin of file
  301.                   // read the note structure
  302.                   file.read( (char*)¬e, sizeof( note ) ) ;
  303.                   while ( !file.eof() )
  304.                     { // play the note
  305.                     float del = note.delay;
  306.                     ch =  note.letter ;
  307.                     kstatus = pushed ;
  308.                     int i = noteptr( ch ) ;
  309.                     keyptr[ i ] -> drawkey() ;
  310.                     keyptr[ i ] -> makesound(del) ;
  311.                     kstatus = notpushed ;
  312.                     keyptr[ i ] -> drawkey() ;
  313.                                         file.read( (char*)¬e, sizeof( note ) ) ;
  314.                     }
  315.                   file.close() ; // close the file
  316.                   break;
  317.                   }
  318.             default: {
  319.                  invalidoption();  // invalid option
  320.                  }
  321.             }
  322.         cleartext() ;
  323.         option = mainmenu() ;        // get another option
  324.         option = toupper( option ) ;
  325.         }
  326.     while ( option != 'D' ) ;    // 'D' means quit
  327.  
  328.     cleardevice() ;        // clear the graphics screen
  329.     closegraph();        // shuts down the graphics system
  330.     return(0) ;        // return zero, program ran ok
  331.     }
  332.  
  333.  
  334.  
  335.  
  336. char mainmenu()            // the main menu for user option
  337.     {
  338.     char choice ;
  339.     gotoxy( 1, 1    ) ; cout << "    P I A N O    S I M U L A T I O N " ;
  340.     gotoxy( 1, 2    ) ; cout << " ---------------------------------------- " ;
  341.     gotoxy( 5, 13  ) ; cout << "   A.  This option allows you to play " ;
  342.     gotoxy( 5, 14  ) ; cout << "       the keyboard like a piano.   " ;
  343.     gotoxy( 5, 16  ) ; cout << "   B.  This option will play a song: " ;
  344.     gotoxy( 5, 17  ) ; cout << "       \'You really got a hold on me.\'" ;
  345.     gotoxy( 5, 19 )  ; cout << "   C.  This option will play a scale . " ;
  346.     gotoxy( 5, 21 ) ; cout << "   D.  Quit program " ;
  347.     gotoxy( 5, 24 ) ; cout << "       ENTER OPTION: " ;
  348.     gotoxy( 30, 24) ; choice = getch() ;
  349.     return ( choice ) ;
  350.     }
  351.  
  352. void cleartext()        // clears the mainmenu() text
  353.     {
  354.     for ( int j=13; j<30; j++ )
  355.         {
  356.         gotoxy( 1, j ) ;
  357.         cout << "                           \
  358.                               ";
  359.         }
  360.     }
  361.  
  362. void showkeyboard()    // displays message on how to play the keyboard
  363.     {
  364.     gotoxy(  5, 13 ) ; cout << "   W  E     T  Y  U     O    " ;
  365.     gotoxy(  5, 14 ) ; cout << "  A  S  D  F  G  H  J  K  L  " ;
  366.     gotoxy( 35, 13 ) ; cout << " <- THESE ARE THE BLACK KEYS " ;
  367.     gotoxy( 35, 14 ) ; cout << " <- THESE ARE THE WHITE KEYS " ;
  368.     gotoxy(  5, 18 ) ; cout << " PLAY THESE LETTERS ON THE KEYBOARD " ;
  369.     gotoxy(  5, 20 ) ; cout << " TYPE 'x' TO EXIT. " ;
  370.     }
  371.  
  372.  
  373.  
  374. int noteptr( char c )    // returns an index to a pointer value
  375.     {
  376.     if ( c == 'a' ) return(  0 );
  377.     if ( c == 'w' ) return(  1 );
  378.     if ( c == 's' ) return(  2 );
  379.     if ( c == 'e' ) return(  3 );
  380.     if ( c == 'd' ) return(  4 );
  381.     if ( c == 'f' ) return(  5 );
  382.     if ( c == 't' ) return(  6 );
  383.     if ( c == 'g' ) return(  7 );
  384.     if ( c == 'y' ) return(  8 );
  385.     if ( c == 'h' ) return(  9 );
  386.     if ( c == 'u' ) return( 10 );
  387.     if ( c == 'j' ) return( 11 );
  388.     if ( c == 'k' ) return( 12 );
  389.     if ( c == 'o' ) return( 13 );
  390.     if ( c == 'l' ) return( 14 );
  391.     else return ( 99 ) ;
  392.     }
  393.  
  394. void invalidoption()    // invalid option selected - displays message
  395.     {
  396.     gotoxy( 5, 22 );  cout << "\a\aInvalid option - try again. " ;
  397.     gotoxy( 5, 24 ) ; cout << "Hit any key... " ;
  398.     getch() ;
  399.     gotoxy( 5 , 22 ) ; cout << "                               ";
  400.     gotoxy( 5 , 24 ) ; cout << "                               ";
  401.     }